#include "ServerConfigure.h"
#include "fstream"
#include "nlohmann/json.hpp"
#include "Log.h"
#include "Utils/Utils.h"
#include <iomanip>
// #include "Blocks/GrassBlock.h"
// #include "Blocks/WaterBlock.h"


namespace PocketSurvival
{

    const std::string   default_serverVerisonName           = "x24.07B";
    const std::string   default_host                        = "0.0.0.0";
    const int32_t       default_port                        = 28887;
    const int32_t       default_maxPlayer                   = 20;
    const LoginType     default_loginTYpe                   = LoginType::UnLimit;
    const bool          default_openPvP                     = true;
    const int32_t       default_threadCount                 = 4;
    const int32_t       default_chunkCatchCount             = 256;
    const int32_t       default_viewChunkCount              = 4;
    const std::string   default_password                    = "";
    const std::string   default_worldDefaultName            = "World";
    static int32_t      default_worldDefaultSeed            = 0;
    const GameMode      default_gameMode                    = GameMode::Challenging;
    const float         default_defaultBiomeSize            = 1.0f;
    const int32_t       default_defaultSeaLevelOffset       = 0;
    const float         default_defaultTemperatureOffset    = 0.0f;
    const float         default_defaultsetHumidityOffset    = 0.0f;
    const TerrainGenerationMode default_defalutTerrainMode  = TerrainGenerationMode::Continent;
    const Vector2       default_defaultIslandSize           = Vector2(400.0f, 400.0f);
    const int32_t       default_defaultTerrainLevel         = 64;
    const float         default_defaultShoreRoughness       = 1.0f;

    // const int32_t       default_defaultTerrainBlockIndex    = GrassBlock::Index();
    const int32_t       default_defaultTerrainBlockIndex    = 8;
    // const int32_t       default_defaultTerrainOceanBlockIndex = WaterBlock::Index();
    const int32_t       default_defaultTerrainOceanBlockIndex = 18;

    const EnvironmentBehaviorMode default_environmentMode   = EnvironmentBehaviorMode::Living;
    const TimeOfDayMode default_timeOfDayMode               = TimeOfDayMode::Changing;
    const float         default_recoverFator                = 1.0f;
    const float         default_daySpeed                    = 1.0f;
    const bool          default_areWeatherEffectsEnabled    = true;
    const bool          default_isAdventureRespawnAllowed   = true;
    const bool          default_areAdventureSurvivalMechanicsEnabled = true;
    const bool          default_areSupernaturalCreaturesEnabled = true;
    const bool          default_canCustomSkin               = true;
    const uint32_t      default_skinMaxSize                 = 64;
    const bool          default_deadNotDrop                 = false;
    const uint8_t       default_tick                        = 20;
    const float         default_terrainChunkRecycleTime     = 5.0f;
    const uint32_t      default_playerChunkRadius           = 4;
    const Point3        default_startSpawnPoint             = Point3 { 100, 72, 100 };
    const float         default_startSpawnPointRadius       = 8.0f;
    const bool          default_useConfusionGuid            = false;

    const bool          default_use0304                     = true;     // 默认使用 x24.03.04


    ServerConfigure::ServerConfigure()
    {
        default_worldDefaultSeed = rd();

        // 加载settings.json
        std::ifstream inputFile("settings.json");
        if (inputFile)
        {
            try
            {
                nlohmann::json jsonData;
                inputFile >> jsonData;

                Utils::GetJsonValue<std::string>(jsonData, serverVerisonName, "ServerVerisonName", default_serverVerisonName);
                Utils::GetJsonValue<std::string>(jsonData, host,              "Host",              default_host);
                Utils::GetJsonValue<int32_t>(    jsonData, port,              "Port",              default_port);
                Utils::GetJsonValue<int32_t>(    jsonData, maxPlayer,         "MaxPlayer",         default_maxPlayer);
                Utils::GetJsonValue<LoginType>(  jsonData, loginType,         "LoginType",         default_loginTYpe);

                Utils::GetJsonValue<bool>(       jsonData, openPvP,           "OpenPvP",           default_openPvP);
                Utils::GetJsonValue<int32_t>(    jsonData, threadCount,       "ThreadCount",       default_threadCount);
                Utils::GetJsonValue<int32_t>(    jsonData, chunkCatchCount,   "ChunkCatchCount",   default_chunkCatchCount);
                Utils::GetJsonValue<int32_t>(    jsonData, viewChunkCount,    "ViewChunkCount",    default_viewChunkCount);
                Utils::GetJsonValue<std::string>(jsonData, password,          "Password",          default_password);
                Utils::GetJsonValue<std::string>(jsonData, worldDefaultName,  "WorldDefaultName",  default_worldDefaultName);
                Utils::GetJsonValue<int32_t>(    jsonData, worldDefaultSeed,  "WorldDefaultSeed",  default_worldDefaultSeed);
                Utils::GetJsonValue<GameMode>(   jsonData, gameMode,          "GameMode",          default_gameMode);

                Utils::GetJsonValue<float>(jsonData, defaultBiomeSize, "DefaultBiomeSize", default_defaultBiomeSize);
                Utils::GetJsonValue<int32_t>(jsonData, defaultSeaLevelOffset, "DefaultSeaLevelOffset", default_defaultSeaLevelOffset);
                Utils::GetJsonValue<float>(jsonData, defaultTemperatureOffset, "DefaultTemperatureOffset", default_defaultTemperatureOffset);
                Utils::GetJsonValue<float>(jsonData, defaultsetHumidityOffset, "DefaultsetHumidityOffset", default_defaultsetHumidityOffset);
                Utils::GetJsonValue<TerrainGenerationMode>( jsonData, defalutTerrainMode, "DefalutTerrainMode", default_defalutTerrainMode);
                Utils::GetJsonValue<Vector2>(jsonData, defaultIslandSize, "DefaultIslandSize", default_defaultIslandSize);
                Utils::GetJsonValue<int32_t>(jsonData, defaultTerrainLevel, "DefaultTerrainLevel", default_defaultTerrainLevel);
                Utils::GetJsonValue<float>(jsonData, defaultShoreRoughness, "DefaultShoreRoughness", default_defaultShoreRoughness);

                if(defaultShoreRoughness == 0.0f)
                {
                    defaultShoreRoughness = default_defaultShoreRoughness;
                }

                Utils::GetJsonValue<int32_t>(jsonData, defaultTerrainBlockIndex, "DefaultTerrainBlockIndex", default_defaultTerrainBlockIndex);
                Utils::GetJsonValue<int32_t>(jsonData, defaultTerrainOceanBlockIndex, "DefaultTerrainOceanBlockIndex", default_defaultTerrainOceanBlockIndex);
                Utils::GetJsonValue<EnvironmentBehaviorMode>(jsonData, environmentMode, "EnvironmentMode", default_environmentMode);
                Utils::GetJsonValue<TimeOfDayMode>(jsonData, timeOfDayMode, "TimeOfDayMode", default_timeOfDayMode);
                Utils::GetJsonValue<float>(jsonData, recoverFator, "RecoverFator", default_recoverFator);
                Utils::GetJsonValue<float>(jsonData, daySpeed, "DaySpeed", default_daySpeed);
                Utils::GetJsonValue<bool>(jsonData, areWeatherEffectsEnabled, "AreWeatherEffectsEnabled", default_areWeatherEffectsEnabled);
                Utils::GetJsonValue<bool>(jsonData, isAdventureRespawnAllowed, "IsAdventureRespawnAllowed", default_isAdventureRespawnAllowed);
                Utils::GetJsonValue<bool>(jsonData, areAdventureSurvivalMechanicsEnabled,"AreAdventureSurvivalMechanicsEnabled", default_areAdventureSurvivalMechanicsEnabled);
                Utils::GetJsonValue<bool>(jsonData, areSupernaturalCreaturesEnabled, "AreSupernaturalCreaturesEnabled", default_areSupernaturalCreaturesEnabled);

                Utils::GetJsonValue<bool>(jsonData, canCustomSkin, "CanCustomSkin", default_canCustomSkin);
                Utils::GetJsonValue<uint32_t>(jsonData, skinMaxSize,"SkinMaxSize", default_skinMaxSize);

                Utils::GetJsonValue<bool>(jsonData, deadNotDrop, "DeadNotDrop", default_deadNotDrop);
                Utils::GetJsonValue<uint8_t>(jsonData, tick, "Tick", default_tick);
                Utils::GetJsonValue<float>(jsonData, terrainChunkRecycleTime, "TerrainChunkRecycleTime", default_terrainChunkRecycleTime);
                Utils::GetJsonValue<uint32_t>(jsonData, playerChunkRadius, "PlayerChunkRadius", default_playerChunkRadius);

                Utils::GetJsonValue<Point3>(jsonData, startSpawnPoint, "StartSpawnPoint", default_startSpawnPoint);
                Utils::GetJsonValue<float>(jsonData, startSpawnPointRadius, "StartSpawnPointRadius", default_startSpawnPointRadius);
                Utils::GetJsonValue<bool>(jsonData, useConfusionGuid, "UseConfusionGuid", default_useConfusionGuid);

                Utils::GetJsonValue<bool>(jsonData, use0304, "Use0304", default_use0304);
            }
            catch (const std::exception &e)
            {
                Log::Error(fmt::format("读取配置文件发生错误 : {}", e.what()));
                setDefault();
            }
        }
        else
        {
            setDefault();
        }
        inputFile.close();
        save();
    }



    void ServerConfigure::save()
    {
        nlohmann::json jsonData;
        jsonData["ServerVerisonName"] = serverVerisonName;
        jsonData["Host"] = host;
        jsonData["Port"] = port;
        jsonData["MaxPlayer"] = maxPlayer;
        
        jsonData["LoginType"] = loginType;

        jsonData["OpenPvP"] = openPvP;
        jsonData["ThreadCount"] = threadCount;
        jsonData["ChunkCatchCount"] = chunkCatchCount;
        jsonData["ViewChunkCount"] = viewChunkCount;
        jsonData["Password"] = password;
        jsonData["WorldDefaultName"] = worldDefaultName;
        jsonData["WorldDefaultSeed"] = worldDefaultSeed;
        jsonData["GameMode"] = gameMode;

        jsonData["DefaultBiomeSize"] = defaultBiomeSize;
        jsonData["DefaultSeaLevelOffset"] = defaultSeaLevelOffset;
        jsonData["DefaultTemperatureOffset"] = defaultTemperatureOffset;
        jsonData["DefaultsetHumidityOffset"] = defaultsetHumidityOffset;
        jsonData["DefalutTerrainMode"] = defalutTerrainMode;
        jsonData["DefaultIslandSize"] = defaultIslandSize;
        jsonData["DefaultTerrainLevel"] = defaultTerrainLevel;
        jsonData["DefaultShoreRoughness"] = defaultShoreRoughness;
        jsonData["DefaultTerrainBlockIndex"] = defaultTerrainBlockIndex;
        jsonData["DefaultTerrainOceanBlockIndex"] = defaultTerrainOceanBlockIndex;
        jsonData["EnvironmentMode"] = environmentMode;
        jsonData["TimeOfDayMode"] = timeOfDayMode;
        jsonData["RecoverFator"] = recoverFator;
        jsonData["DaySpeed"] = daySpeed;
        jsonData["AreWeatherEffectsEnabled"] = areWeatherEffectsEnabled;
        jsonData["IsAdventureRespawnAllowed"] = isAdventureRespawnAllowed;
        jsonData["AreAdventureSurvivalMechanicsEnabled"] = areAdventureSurvivalMechanicsEnabled;
        jsonData["AreSupernaturalCreaturesEnabled"] = areSupernaturalCreaturesEnabled;

        jsonData["CanCustomSkin"] = canCustomSkin;
        jsonData["SkinMaxSize"] = skinMaxSize;

        jsonData["DeadNotDrop"] = deadNotDrop;
        jsonData["Tick"] = tick;
        jsonData["TerrainChunkRecycleTime"] = terrainChunkRecycleTime;
        jsonData["PlayerChunkRadius"] = playerChunkRadius;

        jsonData["StartSpawnPoint"] = startSpawnPoint;
        jsonData["StartSpawnPointRadius"] = startSpawnPointRadius;
        jsonData["UseConfusionGuid"] = useConfusionGuid;
        jsonData["Use0304"] = use0304;

        std::ofstream outStream("settings.json");
        if(outStream)
        {
            outStream << std::setw(4) << jsonData;
        }
        else
        {
            Log::Error("配置文件保存失败");
        }
        outStream.close();
    }



    void ServerConfigure::setDefault()
    {
        serverVerisonName       = default_serverVerisonName;
        host                    = default_host;
        port                    = default_port;
        maxPlayer               = default_maxPlayer;
        loginType               = default_loginTYpe;

        openPvP                 = default_openPvP;
        threadCount             = default_threadCount;
        chunkCatchCount         = default_chunkCatchCount;
        viewChunkCount          = default_viewChunkCount;
        password                = default_password;
        worldDefaultName        = default_worldDefaultName;
        worldDefaultSeed        = default_worldDefaultSeed;
        gameMode                = default_gameMode;

        defaultBiomeSize                = default_defaultBiomeSize;
        defaultSeaLevelOffset           = default_defaultSeaLevelOffset;
        defaultTemperatureOffset        = default_defaultTemperatureOffset;
        defaultsetHumidityOffset        = default_defaultsetHumidityOffset;
        defalutTerrainMode              = default_defalutTerrainMode;
        defaultIslandSize               = default_defaultIslandSize;
        defaultTerrainLevel             = default_defaultTerrainLevel;
        defaultShoreRoughness           = default_defaultShoreRoughness;
        defaultTerrainBlockIndex        = default_defaultTerrainBlockIndex;
        defaultTerrainOceanBlockIndex   = default_defaultTerrainOceanBlockIndex;
        environmentMode                 = default_environmentMode;
        timeOfDayMode                   = default_timeOfDayMode;
        recoverFator                    = default_recoverFator;
        daySpeed                        = default_daySpeed;
        areWeatherEffectsEnabled        = default_areWeatherEffectsEnabled;
        isAdventureRespawnAllowed       = default_isAdventureRespawnAllowed;
        areAdventureSurvivalMechanicsEnabled = default_areAdventureSurvivalMechanicsEnabled;
        areSupernaturalCreaturesEnabled = default_areSupernaturalCreaturesEnabled;
        canCustomSkin                   = default_canCustomSkin;
        skinMaxSize                     = default_skinMaxSize;
        deadNotDrop                     = default_deadNotDrop;
        tick                            = default_tick;
        terrainChunkRecycleTime         = default_terrainChunkRecycleTime;
        playerChunkRadius               = default_playerChunkRadius;

        startSpawnPoint                 = default_startSpawnPoint;
        startSpawnPointRadius           = default_startSpawnPointRadius;
        useConfusionGuid                = default_useConfusionGuid;
        use0304                         = default_use0304;
    }

    ServerConfigure::~ServerConfigure() {}

}